Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | 'use client'; import { Center, Container, Grid, Loader, Paper, Stack, Title, } from '@mantine/core'; import type { Route } from 'next'; import { useTranslations } from 'next-intl'; import { BackTo } from '@/components/buttons/BackTo'; import RecipeRating from '@/components/Recipe/Rating'; import { RecipeHero } from './components/RecipeHero'; import { RecipeIngredients } from './components/RecipeIngredients'; import { RecipeNotFound } from './components/RecipeNotFound'; import { RecipeSteps } from './components/RecipeSteps'; import { RecipeVideo } from './components/RecipeVideo'; import { useRecipeDetail } from './hooks/useRecipeDetail'; import type { RecipeDetailClientProps } from './types'; const RecipeDetailClient = ({ recipeId, }: Readonly<RecipeDetailClientProps>) => { const translate = useTranslations('recipeDetail'); const { recipe, loading, error, servingMultiplier, adjustedServings, checkedIngredients, toggleIngredient, incrementServings, decrementServings, youtubeId, isOwner, sortedSteps, } = useRecipeDetail(recipeId); if (loading) { return ( <Center h="60vh"> <Loader size="lg" type="dots" /> </Center> ); } if (error || !recipe) { return <RecipeNotFound errorMessage={error?.message} />; } return ( <Container size="xl" py="xl"> <Stack gap="xl"> <BackTo href={'/recipes' as Route} text={translate('backToRecipes')} /> <RecipeHero recipe={recipe} isOwner={isOwner} /> <Grid gap="xl"> {/* Left column – Steps */} <Grid.Col span={{ base: 12, md: 7 }}> <Stack gap="xl"> <RecipeSteps steps={sortedSteps} /> {youtubeId && ( <RecipeVideo youtubeId={youtubeId} title={recipe.title} /> )} {/* Rating */} <Paper p="lg" radius="md" withBorder> <Title order={3} size="h4" mb="sm"> {translate('rateThisRecipe')} </Title> <RecipeRating recipeId={recipe.id} userRating={recipe.userRating ?? undefined} averageRating={recipe.averageRating} ratingsCount={recipe.ratingsCount} /> </Paper> </Stack> </Grid.Col> {/* Right column – Ingredients (sticky) */} <Grid.Col span={{ base: 12, md: 5 }}> <RecipeIngredients ingredients={recipe.ingredients} servingMultiplier={servingMultiplier} adjustedServings={adjustedServings} checkedIngredients={checkedIngredients} onToggleIngredient={toggleIngredient} onIncrementServings={incrementServings} onDecrementServings={decrementServings} /> </Grid.Col> </Grid> </Stack> </Container> ); }; export default RecipeDetailClient; |